/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Domain;

import Domain.Player.Disc;
import domain.player.Computer;
import domain.player.Player;
import domain.player.PlayerType;
import java.util.Random;

/**
 *
 * @author sa11
 */
public class GameManager {

    private GameGrid gameGrid;
    private DomainController logicController;
    private Player player1;
    private Player player2;
    private int currentPlayerNum;
    private boolean debug = false;

    public GameManager(DomainController logicController, GameGrid gameGrid) {
        this.gameGrid = gameGrid;
        this.logicController = logicController;
    }

    /**
     * Starts the game by executing the GameLoop class
     */
    public void startGame() {
        gameLoop();
    }

    /**
     * GameLoop class utilizing the SwingWorker class
     */
    private void gameLoop() {
        new Thread(new Runnable() {

            @Override
            public void run() {
                currentPlayerNum = 1;
                gameGrid = logicController.getGameGrid();

                while (!hasEnded()) {
                    logicController.setCurrentPlayerFrameName(getCurrentPlayer());
                    makeNextMove();
                }

                Player winner = getWinner();
                if (winner != null) {
                    logicController.presentWinnerBoard();
                    logicController.showWinnerDialog(winner);
                } else if (gameGrid.isTie()) {
                    logicController.showDrawnDialog();
                }
            }
        }).start();
    }

    /**
     * Add players to the game
     *
     * @param player1
     * @param player2
     */
    public void addPlayers(Player player1, Player player2) {
        this.player1 = player1;
        this.player2 = player2;

        randomizeStartPlayer();
    }

    /**
     * Randomize start player
     */
    public void randomizeStartPlayer() {
        if (player1 != null && player2 != null) {
            currentPlayerNum = (new Random().nextInt() % 2 == 0 ? 1 : 2);
        }
    }

    /**
     * Returns a Player object corresponding to playerNum
     */
    public Player getPlayer(int playerNum) {
        return (playerNum % 2 == 0 ? player2 : player1);
    }

    /**
     * Returns the Player object for the current player
     */
    public Player getCurrentPlayer() {
        return (currentPlayerNum % 2 == 0 ? player2 : player1);
    }

    /**
     * Change the current player
     */
    public void changeCurrentPlayer() {
        currentPlayerNum = getCurrentPlayer().getDiscID().
                equals(player1.getDiscID()) ? 2 : 1;
    }

    /**
     * Executes the next move
     */
    public boolean makeNextMove() {
        Square move = logicController.getNextMove();
        int row = move.getX();
        int column = move.getY();

        if (gameGrid.isValidMove(row, column)) {
            // used for debug
            if (getCurrentPlayer().getType() == PlayerType.COMPUTER && debug) {
           /*     int nrOfMovesMM = 0;
                int nrOfMovesMMABP = 0;
                Square tempMove = new Square();
                int score = 0;
                Computer p = (Computer) getCurrentPlayer();
                if (p.getAIType() == AI.AI_MINIMAX) {
                    nrOfMovesMM = p.getNrOfEvaluatedMoves();
                    System.out.println("score " + p.getScoreForMove());
                    p.setAIType(AI.AI_MINMAX);
                    System.out.println("setting to AI_MINMAX");
                    tempMove.setX(logicController.getNextMove().getX());
                    tempMove.setY(logicController.getNextMove().getY());
                    nrOfMovesMMABP = p.getNrOfEvaluatedMoves();
                    score = p.getScoreForMove();
                    p.setAIType(AI.AI_MINIMAX);
                } else {
                    nrOfMovesMMABP = p.getNrOfEvaluatedMoves();
                    System.out.println("score " + p.getScoreForMove());
                    p.setAIType(AI.AI_MINIMAX);
                    System.out.println("setting to AI_MINIMAX");
                    logicController.getNextMove();
                    nrOfMovesMM = p.getNrOfEvaluatedMoves();
                    score = p.getScoreForMove();
                    p.setAIType(AI.AI_MINMAX);
                }

                System.out.println("score2 " + score);
                System.out.println("Moves = " + row + " and " + tempMove.getX());
                System.out.println("Moves = " + column + " and " + tempMove.getY());
                logicController.presentMoveWithAndWithout(score, nrOfMovesMM, nrOfMovesMMABP);
*/
            }

            logicController.addDisc(row, column);
            changeCurrentPlayer();
            return true;
        }
        return false;
    }

    /**
     * Returns true if the current game has ended
     */
    private boolean hasEnded() {
        return gameGrid.isTie() || gameGrid.hasWon();
    }

    /**
     * Returns the winner as a Player object, null if none
     */
    private Player getWinner() {
        if (gameGrid.getWinner() != Disc.NONE) {
            return (player1.getDiscID() == gameGrid.getWinner()
                    ? player1 : player2);
        }
        return null;
    }

    public void setDebug(boolean debug) {
        this.debug = (this.debug == debug) ? invers(debug) : debug;
    }

    private boolean invers(boolean debug) {
        return debug == true ? false : true;
    }

    public void setGameGrid(GameGrid gameGrid) {
        this.gameGrid = gameGrid;
    }
}
